"""
错误处理工具模块
"""
import logging
import traceback
from functools import wraps
from typing import Optional, Dict, Any, Callable
from datetime import datetime

from shared.enums import ErrorType

logger = logging.getLogger(__name__)


class ErrorHandler:
    """统一错误处理器"""
    
    def __init__(self):
        self.error_handlers: Dict[ErrorType, Callable] = {
            ErrorType.API_ERROR: self._handle_api_error,
            ErrorType.VALIDATION_ERROR: self._handle_validation_error,
            ErrorType.EXECUTION_TIMEOUT: self._handle_timeout_error,
            ErrorType.AGENT_UNAVAILABLE: self._handle_agent_unavailable,
            ErrorType.QUESTION_ANALYSIS_FAILED: self._handle_analysis_failed,
            ErrorType.TASK_GENERATION_FAILED: self._handle_task_generation_failed,
            ErrorType.EXECUTION_FAILED: self._handle_execution_failed
        }
    
    def handle_error(self, error_type: ErrorType, error: Exception, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """处理错误"""
        context = context or {}
        
        # 记录错误
        self._log_error(error_type, error, context)
        
        # 获取错误处理器
        handler = self.error_handlers.get(error_type, self._handle_generic_error)
        
        # 执行错误处理
        return handler(error, context)
    
    def _log_error(self, error_type: ErrorType, error: Exception, context: Dict[str, Any]):
        """记录错误日志"""
        logger.error(
            f"Error occurred - Type: {error_type.value}, "
            f"Error: {str(error)}, "
            f"Context: {context}, "
            f"Traceback: {traceback.format_exc()}"
        )
    
    def _handle_api_error(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理API错误"""
        return {
            'error_type': ErrorType.API_ERROR.value,
            'message': 'API调用失败，请稍后重试',
            'user_message': 'AI服务暂时不可用，请稍后重试',
            'recoverable': True,
            'retry_after': 60
        }
    
    def _handle_validation_error(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理验证错误"""
        return {
            'error_type': ErrorType.VALIDATION_ERROR.value,
            'message': str(error),
            'user_message': f'输入验证失败：{str(error)}',
            'recoverable': False
        }
    
    def _handle_timeout_error(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理超时错误"""
        return {
            'error_type': ErrorType.EXECUTION_TIMEOUT.value,
            'message': '执行超时',
            'user_message': '处理时间过长，已自动取消。请尝试简化问题或稍后重试',
            'recoverable': True,
            'retry_after': 300
        }
    
    def _handle_agent_unavailable(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理智能体不可用错误"""
        return {
            'error_type': ErrorType.AGENT_UNAVAILABLE.value,
            'message': '智能体服务不可用',
            'user_message': 'AI智能体暂时不可用，系统正在尝试恢复',
            'recoverable': True,
            'retry_after': 120
        }
    
    def _handle_analysis_failed(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理问题分析失败"""
        return {
            'error_type': ErrorType.QUESTION_ANALYSIS_FAILED.value,
            'message': '问题分析失败',
            'user_message': '无法分析问题复杂度，将使用默认处理方式',
            'recoverable': True,
            'fallback_action': 'use_default_analysis'
        }
    
    def _handle_task_generation_failed(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理任务生成失败"""
        return {
            'error_type': ErrorType.TASK_GENERATION_FAILED.value,
            'message': '任务生成失败',
            'user_message': '无法生成任务序列，将使用默认任务模板',
            'recoverable': True,
            'fallback_action': 'use_default_tasks'
        }
    
    def _handle_execution_failed(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理执行失败"""
        return {
            'error_type': ErrorType.EXECUTION_FAILED.value,
            'message': '任务执行失败',
            'user_message': '任务执行过程中出现错误，已保存部分结果',
            'recoverable': True,
            'fallback_action': 'return_partial_results'
        }
    
    def _handle_generic_error(self, error: Exception, context: Dict[str, Any]) -> Dict[str, Any]:
        """处理通用错误"""
        return {
            'error_type': 'generic_error',
            'message': str(error),
            'user_message': '系统出现未知错误，请稍后重试',
            'recoverable': True,
            'retry_after': 60
        }


def error_handler(error_type: ErrorType = None):
    """错误处理装饰器"""
    def decorator(func):
        @wraps(func)
        async def async_wrapper(*args, **kwargs):
            try:
                return await func(*args, **kwargs)
            except Exception as e:
                handler = ErrorHandler()
                context = {
                    'function': func.__name__,
                    'args': str(args)[:200],
                    'kwargs': str(kwargs)[:200],
                    'timestamp': datetime.now().isoformat()
                }
                
                detected_error_type = error_type or _detect_error_type(e)
                error_info = handler.handle_error(detected_error_type, e, context)
                
                # 根据错误类型决定是否重新抛出异常
                if error_info.get('recoverable', True):
                    logger.warning(f"Recoverable error in {func.__name__}: {error_info['message']}")
                    return None
                else:
                    raise e
        
        @wraps(func)
        def sync_wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                handler = ErrorHandler()
                context = {
                    'function': func.__name__,
                    'args': str(args)[:200],
                    'kwargs': str(kwargs)[:200],
                    'timestamp': datetime.now().isoformat()
                }
                
                detected_error_type = error_type or _detect_error_type(e)
                error_info = handler.handle_error(detected_error_type, e, context)
                
                if error_info.get('recoverable', True):
                    logger.warning(f"Recoverable error in {func.__name__}: {error_info['message']}")
                    return None
                else:
                    raise e
        
        # 检查是否是异步函数
        import inspect
        if inspect.iscoroutinefunction(func):
            return async_wrapper
        else:
            return sync_wrapper
    
    return decorator


def _detect_error_type(error: Exception) -> ErrorType:
    """自动检测错误类型"""
    error_str = str(error).lower()
    
    if 'timeout' in error_str:
        return ErrorType.EXECUTION_TIMEOUT
    elif 'api' in error_str or 'request' in error_str:
        return ErrorType.API_ERROR
    elif 'validation' in error_str or 'invalid' in error_str:
        return ErrorType.VALIDATION_ERROR
    else:
        return ErrorType.EXECUTION_FAILED


class RetryManager:
    """重试管理器"""
    
    def __init__(self, max_retries: int = 3, base_delay: float = 1.0):
        self.max_retries = max_retries
        self.base_delay = base_delay
    
    async def retry_async(self, func: Callable, *args, **kwargs):
        """异步重试"""
        import asyncio
        
        last_exception = None
        
        for attempt in range(self.max_retries + 1):
            try:
                if attempt > 0:
                    delay = self.base_delay * (2 ** (attempt - 1))  # 指数退避
                    logger.info(f"Retrying {func.__name__} in {delay} seconds (attempt {attempt + 1})")
                    await asyncio.sleep(delay)
                
                return await func(*args, **kwargs)
                
            except Exception as e:
                last_exception = e
                if attempt < self.max_retries:
                    logger.warning(f"Attempt {attempt + 1} failed for {func.__name__}: {e}")
                else:
                    logger.error(f"All {self.max_retries + 1} attempts failed for {func.__name__}")
        
        raise last_exception
    
    def retry_sync(self, func: Callable, *args, **kwargs):
        """同步重试"""
        import time
        
        last_exception = None
        
        for attempt in range(self.max_retries + 1):
            try:
                if attempt > 0:
                    delay = self.base_delay * (2 ** (attempt - 1))
                    logger.info(f"Retrying {func.__name__} in {delay} seconds (attempt {attempt + 1})")
                    time.sleep(delay)
                
                return func(*args, **kwargs)
                
            except Exception as e:
                last_exception = e
                if attempt < self.max_retries:
                    logger.warning(f"Attempt {attempt + 1} failed for {func.__name__}: {e}")
                else:
                    logger.error(f"All {self.max_retries + 1} attempts failed for {func.__name__}")
        
        raise last_exception


def with_retry(max_retries: int = 3, base_delay: float = 1.0):
    """重试装饰器"""
    def decorator(func):
        retry_manager = RetryManager(max_retries, base_delay)
        
        @wraps(func)
        async def async_wrapper(*args, **kwargs):
            return await retry_manager.retry_async(func, *args, **kwargs)
        
        @wraps(func)
        def sync_wrapper(*args, **kwargs):
            return retry_manager.retry_sync(func, *args, **kwargs)
        
        import inspect
        if inspect.iscoroutinefunction(func):
            return async_wrapper
        else:
            return sync_wrapper
    
    return decorator


# 全局错误处理器实例
global_error_handler = ErrorHandler()